/*
 * BlackLightning.PluginLib.Modules.IPacketHandler
 * Andy Tidball
 * 
 * Project: Black Lightning Plugin Library
 * Copyright: GNU General Public License
 */

using System;
using BlackLightning.PluginLib;

namespace BlackLightning.PluginLib.Modules {
	/// <summary>
	/// Defines the interface between Black Lightning and anything that can send and receive packets.
	/// </summary>
	public interface IPacketHandler : IMessageHandler {
		/// <summary>
		/// Raised by the IPacketHandler to send a Packet to Black Lightning and possibly on to either the front end or game server.
		/// </summary>
		event SendPacketEventHandler SendPacket;

		/// <summary>
		/// Called by Black Lightning to have the IPacketHandler handle a Packet that it has registered to receive.
		/// </summary>
		/// <param name="Packet">The Packet being sent to the IObject.</param>
		void HandlePacket(ref BLPacket Packet);
	}
	
	/// <summary>
	/// The prototype for the SendPacket event.
	/// </summary>
	/// <param name="Sender">The IModule which sent the packet.</param>
	/// <param name="e">Arguments about the packet being sent.</param>
	public delegate void SendPacketEventHandler(object Sender, SendPacketEventArgs e);

	/// <summary>
	/// The arguments sent with a SendPacket event.
	/// </summary>
	[Serializable]
	public class SendPacketEventArgs : EventArgs {
		// member data
		private BLPacket _Packet; // the packet being sent

		/// <summary>
		/// Creates a new SendPacketEventArgs.
		/// </summary>
		/// <param name="Packet">The packet to be sent.</param>
		public SendPacketEventArgs(BLPacket Packet) {
			_Packet = Packet;
		}

		/// <summary>
		/// Gets the packet being sent.
		/// </summary>
		public BLPacket Packet {
			get {
				return _Packet;
			}
		}
	}

	/// <summary>
	/// A helper class that implements IPacketHandler and provides helper functionality for derived classes.
	/// </summary>
	public abstract class PacketHandler : MessageHandler, IPacketHandler {
		/// <summary>
		/// Fired whenever the Module has a packet that needs to be delivered.
		/// </summary>
		public event SendPacketEventHandler SendPacket;

		/// <summary>
		/// Fires the SendPacket event.
		/// </summary>
		/// <param name="e">Arguments to pass with the SendPacket event.</param>
		protected void OnSendPacket(SendPacketEventArgs e) {
			if (SendPacket != null) {
				SendPacket(this, e);
			}
		}

		/// <summary>
		/// Wraps the given Packet in SendPacketEventArgs and fires the SendPacket event.
		/// </summary>
		/// <param name="P">The Packet to send.</param>
		protected void Send(BLPacket P) {
			OnSendPacket(new SendPacketEventArgs(P));
		}

		/// <summary>
		/// Creates a RawBLPacket with the given data and sends it to the front end.
		/// </summary>
		/// <param name="Data">The data to send to the front end.</param>
		protected void SendToFrontEnd(string Data) {
			Send(new RawBLPacket(Program.BlackLightning, Program.FrontEnd, Data));
		}

		/// <summary>
		/// Creates a RawBLPacket with the given data and sends it to the game server.
		/// </summary>
		/// <param name="Data">The data to send to the game server.</param>
		protected void SendToGameServer(string Data) {
			Send(new RawBLPacket(Program.BlackLightning, Program.GameServer, Data));
		}

		/// <summary>
		/// Wraps the given filter in a RegisterPacketMessage and sends it.
		/// </summary>
		/// <param name="Filter">The filter to register with Black Lightning.</param>
		protected void RegisterPacket(BLPacketFilter Filter) {
			Send(new RegisterPacketMessage(Filter));
		}

		/// <summary>
		/// Wraps the given filter in a RegisterPacketMessage and sends it.
		/// </summary>
		/// <param name="Filter">The filter to register with Black Lightning.</param>
		/// <param name="Priority">The priority level to handle matching Packets at.</param>
		protected void RegisterPacket(BLPacketFilter Filter, Priority Priority) {
			Send(new RegisterPacketMessage(Filter, Priority));
		}

		/// <summary>
		/// Wraps the given filter in a RegisterPacketMessage and sends it.
		/// </summary>
		/// <param name="Filter">The filter to register with Black Lightning.</param>
		/// <param name="Priority">The priority level to handle matching Packets at.</param>
		/// <param name="NewThread">Whether or not to handle matching Packets in a new thread.</param>
		protected void RegisterPacket(BLPacketFilter Filter, Priority Priority, bool NewThread) {
			Send(new RegisterPacketMessage(Filter, Priority, NewThread));
		}

		/// <summary>
		/// Wraps the given filter in an UnregisterPacketMessage and sends it.
		/// </summary>
		/// <param name="Filter">The filter to unregister from Black Lightning.</param>
		protected void UnregisterPacket(BLPacketFilter Filter) {
			Send(new UnregisterPacketMessage(Filter));
		}

		/// <summary>
		/// Called when a Packet is going through Black Lightning that this Module has registered to receive.
		/// </summary>
		/// <param name="Packet">The Packet going through Black Lightning that the Module registered to receive.</param>
		public abstract void HandlePacket(ref BLPacket Packet);
	}
}
